package icasue.reflect.handles.predicate;

import icasue.reflect.handles.HandleSupplier;
import icasue.reflect.handles.OFAble;
import icasue.reflect.handles.fields.FieldOF;
import icasue.reflect.handles.object.ObjectOF;
import icasue.reflect.handles.util.OFUtil;
import icasue.reflect.exceptions.HandleException;
import icasue.reflect.handles.classes.ClassOF;
import icasue.reflect.handles.exception.ExceptionOF;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;

/**
 * @Author: Qiao Hang
 * @CreateDate: 2020/12/3 下午7:01
 * @UpdateDate:
 * @Description:
 */
public class SureOF implements OFAble {

    /**
     *  equals_ (left,right)
     *  isNull_ (obj)
     *  notNull_ (obj)
     *  notNullAll_ (obj...)
     *  isAry_ (aryObj)     doc: predicate supplied obj is instanceOf array.
     *  isCls_ (cls)        doc: predicate supplied cls is a class element.
     *  isStr_ (str)        doc: predicate supplied cls is a String element.
     *  isColl_ (coll)      doc: predicate supplied cls is instanceOf Collection, of course include List, Set.
     *  isNum_ (obj)        doc: predicate supplied cls is instanceOf Number, of course include Int, Float, Double, Short.
     *  isInt_ (iObj)       doc: predicate supplied cls is instanceOf Integer.
     *  isDouble_ (iObj)       doc: predicate supplied cls is instanceOf Double.
     *  isFloat_ (iObj)       doc: predicate supplied cls is instanceOf Float.
     *  isShort_ (iObj)       doc: predicate supplied cls is instanceOf Short.
     *  notEmptyAry_ (ary)    doc: predicate ary you supplied is not a empty array, deep check, include inner elements.
     *  notEmptyList_ (list)  doc: predicate list you supplied is not a empty list, deep check, include inner elements.
     *  regex_ (sourceAndRegexG)  doc: predicate source content[0] match all regex[1 to maxSize]
     *
     *  All method check pass.
     */

    public static HandleSupplier.ConsumerAry equals_ = (leftRight) -> {
        try {
            SureOF.notEmptyAry_.accept(leftRight);
            if(ObjectOF.equals_.test(leftRight)) return;
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.equals_ : predicate failed.");
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.equals_ : occur an error -> " , throwable.getMessage());
        }
    };

    public static Consumer<Object> isNull_ = (obj) -> {
        try {
            if(ObjectOF.notNull_.test(obj))
                throw ExceptionOF.handleExcInvocation_.apply("SureOF.isNull_ : predicate failed.");
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.isNull_ : occur an error -> " , throwable.getMessage());
        }
    };

    public static Consumer<Object> notNull_ = (obj) -> {
        try {
            if(ObjectOF.isNull_.test(obj))
                throw ExceptionOF.handleExcInvocation_.apply("SureOF.notNull_ : predicate failed.");
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.notNull_ : occur an error -> " , throwable.getMessage());
        }
    };

    public static HandleSupplier.ConsumerAry notNullAll_ = (params) -> {
        try {
            if(!ObjectOF.notNullAll_.test(params))
                throw ExceptionOF.handleExcInvocation_.apply("SureOF.notNullAll_ : predicate failed.");
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.notNullAll_ : occur an error -> " , throwable.getMessage());
        }
    };

    public static Consumer<Object> isAry_ = (obj) -> {
        try {
            SureOF.notNull_.accept(obj);
            if(!ClassOF.isArray_.test(obj.getClass()))
                throw ExceptionOF.handleExcInvocation_.apply("SureOF.isAry_ : predicate failed.");
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.isAry_ : occur an error -> " , throwable.getMessage());
        }
    };

    public static Consumer<Object> isCls_ = (obj) -> {
        try {
            SureOF.notNull_.accept(obj);
            if(ObjectOF.equals_.test(new Object[]{Class.class,obj.getClass()})) return;
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.isCls_ : predicate failed.");
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.isCls_ : occur an error -> " , throwable.getMessage());
        }
    };

    public static Consumer<Object> isStr_ = (str) -> {
        try {
            SureOF.notNull_.accept(str);
            if(ClassOF.isInstance_.test(new Object[]{String.class,str})) return;
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.isStr_ : predicate failed.");
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.isStr_ : occur an error -> " , throwable.getMessage());
        }
    };

    public static Consumer<Object> isColl_ = (obj) -> {
        try {
            SureOF.notNull_.accept(obj);
            if(!ClassOF.isInstance_.test(new Object[]{Collection.class, obj}))
                throw ExceptionOF.handleExcInvocation_.apply("SureOF.isColl_ : predicate failed.");
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.isColl_ : occur an error -> " , throwable.getMessage());
        }
    };


    public static Consumer<Object> isNum_ = (obj) -> {
        try {
            SureOF.notNull_.accept(obj);
            if(obj instanceof Integer || obj instanceof Double || obj instanceof Float || obj instanceof Short) return;
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.isNum_ : predicate failed.");
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.isNum_ : occur an error -> " , throwable.getMessage());
        }
    };

    public static Consumer<Object> isInt_ = (obj) -> {
        try {
            SureOF.notNull_.accept(obj);
            if(obj instanceof Integer) return;
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.isInt_ : predicate failed.");
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.isInt_ : occur an error -> " , throwable.getMessage());
        }
    };

    public static Consumer<Object> isDouble_ = (obj) -> {
        try {
            SureOF.notNull_.accept(obj);
            if(obj instanceof Double) return;
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.isDouble_ : predicate failed.");
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.isDouble_ : occur an error -> " , throwable.getMessage());
        }
    };

    public static Consumer<Object> isFloat_ = (obj) -> {
        try {
            SureOF.notNull_.accept(obj);
            if(obj instanceof Float) return;
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.isFloat_ : predicate failed.");
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.isFloat_ : occur an error -> " , throwable.getMessage());
        }
    };

    public static Consumer<Object> isShort_ = (obj) -> {
        try {
            SureOF.notNull_.accept(obj);
            if(obj instanceof Short) return;
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.isShort_ : predicate failed.");
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.isShort_ : occur an error -> " , throwable.getMessage());
        }
    };

    public static Consumer<Object> notEmptyAry_ = (obj) -> {
        try {
            if(ObjectOF.notEmptyAry_.test(obj)) return;
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.notEmptyAry_ : predicate failed.");
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.notEmptyAry_ : occur an error -> " , throwable.getMessage());
        }
    };

    public static Consumer<Object> notEmptyList_ = (obj) -> {
        try {
            if(ObjectOF.notEmptyList_.test(obj)) return;
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.notEmptyList_ : predicate failed.");
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.notEmptyList_ : occur an error -> " , throwable.getMessage());
        }
    };

    public static HandleSupplier.ConsumerAry regex_ = (strAndRegex) -> {
        try {
            if(!ObjectOF.notEmptyAry_.test(strAndRegex))
                throw ExceptionOF.handleExcInvocation_.apply("SureOF.regex_ : exist null element.");
            if(strAndRegex.length == 1) return;
            Object[] copy = Arrays.copyOfRange(strAndRegex, 1, strAndRegex.length);
            String source = OFUtil.cast(strAndRegex[0], String.class);
            List<String> regexG = OFUtil.aryToList(copy, String.class);
            for (String regex : regexG)
                if (!source.matches(regex))
                    throw ExceptionOF.handleExcInvocation_.apply("SureOF.regex_ : ["+regex+"] predicate failed.");
        } catch (HandleException deepError){
            throw deepError;
        } catch (Throwable throwable) {
            throw ExceptionOF.handleExcInvocation_.apply("SureOF.regex_ : occur an error -> " , throwable.getMessage());
        }
    };

    /**
     * 默认的异常消息构造体
     * @param consumer
     * @param param
     * @param mes
     */
    public static void defaultM(Consumer consumer,Object param, String mes){
        if(ObjectOF.isNull_.test(mes))
            consumer.accept(param);
        else
            try { consumer.accept(param); }catch (HandleException deepError){
                deepError.message = mes;
                FieldOF.set_ofTp_fName_instance_val_.accept(Throwable.class,"detailMessage",deepError,mes);
                throw deepError;
            }
    }
    public static void equals(Object left,Object right,String mes){ defaultM(SureOF.equals_,new Object[]{left, right},mes); }
    public static void isNull(Object obj,String mes){ defaultM(SureOF.isNull_,obj,mes); }
    public static void notNull(Object obj,String mes){ defaultM(SureOF.notNull_,obj,mes); }
    public static void notNullAll(Object[] params,String mes){ defaultM(SureOF.notNullAll_,params,mes); }
    public static void isAry(Object obj,String mes){ defaultM(SureOF.isAry_,obj,mes); }
    public static void isCls(Object obj,String mes){ defaultM(SureOF.isCls_,obj,mes); }
    public static void isStr(Object obj,String mes){ defaultM(SureOF.isStr_,obj,mes); }
    public static void isColl(Object obj,String mes){ defaultM(SureOF.isColl_,obj,mes); }
    public static void isNum(Object obj,String mes){ defaultM(SureOF.isNum_,obj,mes); }
    public static void isDouble(Object obj,String mes){ defaultM(SureOF.isDouble_,obj,mes); }
    public static void isFloat(Object obj,String mes){ defaultM(SureOF.isFloat_,obj,mes); }
    public static void isShort(Object obj,String mes){ defaultM(SureOF.isShort_,obj,mes); }
    public static void notEmptyAry(Object[] obj,String mes){ defaultM(SureOF.notEmptyAry_,obj,mes); }
    public static void notEmptyList(Object obj,String mes){ defaultM(SureOF.notEmptyList_,obj,mes); }
    public static void regex(Object[] params,String mes){ defaultM(SureOF.regex_,params,mes); }
}
